#include "trainview.h"
#include <QFileInfo>
#include "common.h"
#include <QHBoxLayout>
#include <QApplication>
#include <QBitmap>

int TrainView::m_id = qRegisterMetaType<TrainView*>();

TrainView::TrainView(QWidget *parent)
    :ViewObject(parent)
    ,m_paramIdentity(NULL)
    ,m_pos_url("")
    ,m_movie(NULL)
    ,hq_movie(NULL)
{
    setWindowFlags(Qt::FramelessWindowHint);
    setAttribute(Qt::WA_DeleteOnClose);
    m_label = new QLabel(this);
    m_label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    m_layout->addWidget(m_label, 0, Qt::AlignCenter);

#ifdef __linux__
    setFocusPolicy(Qt::NoFocus);
#else
    setFocusPolicy(Qt::StrongFocus);
#endif

    if (m_objectParam == NULL)
        m_objectParam = new ParamObject;

    if (m_paramIdentity == NULL)
        m_paramIdentity = new TrainViewParam;
}

TrainView::~TrainView()
{
    if (m_paramIdentity != NULL)
        delete m_paramIdentity;

    if (m_objectParam != NULL)
        delete  m_objectParam;

    m_paramIdentity = NULL;
    m_objectParam = NULL;
}

void TrainView::FinalShow(QString url)
{
    if (url == "") return;

    AddSuffix(url);
    url.push_front(mPrefix);

    if ("hqv" == url.right(3))
    {
        if (hq_movie == NULL)
        {
            hq_movie = new HuaqiMovie(this);
            if (NULL == hq_movie)
                return;
        }
        else
        {
            hq_movie->stop();
        }

        hq_movie->setFileName(url);
        QStringList list = hq_movie->getImageList();
        if (list.count() < 0)
            return;

        m_label->setFixedSize(QSize(m_objectParam->GetWidth(), m_objectParam->GetHeight()));
        hq_movie->setLabel(m_label);
        hq_movie->showOne();
        hq_movie->start();

#ifndef __linux__
        emit sgl_viewobject_update_to_editwidget(m_objectParam->GetRandom());
#endif
    }
    else
    {
        // 解决设置gif图片之前设置过hqv资源，会继续显示hqv资源
        if (NULL != hq_movie)
        {
            hq_movie->stop();
            hq_movie->setLabel(NULL);
        }

        if ("gif" == url.right(3))
        {
            if (NULL == m_movie)
            {
                m_movie = new QMovie(url, QByteArray(), this);
                if (NULL == m_movie)
                    return;
            }
            else
            {
                m_movie->stop();
            }
            m_movie->setFileName(url);
            m_movie->start();
            m_movie->setScaledSize(QSize(m_objectParam->GetWidth(), m_objectParam->GetHeight()));
            m_label->setMovie(m_movie);

            //这个信号绑定是trainview独有的,目前只支持gif
            connect(m_movie, &QMovie::frameChanged, this, &TrainView::StopGifEnd);
#ifndef __linux__
            emit sgl_viewobject_update_to_editwidget(m_objectParam->GetRandom());
#endif
        }
        else
        {
            QPixmap pixmap(url);
            m_label->setPixmap(pixmap);
            m_label->setScaledContents(true);

#ifndef __linux__
            emit sgl_viewobject_update_to_editwidget(m_objectParam->GetRandom());
#endif
        }
    }
    if (m_change)
    {
        location(m_change_x, m_change_y, m_change_w, m_change_h);
    }
    else
    {
        location(m_objectParam->GetX(), m_objectParam->GetY(),
                    m_objectParam->GetWidth(), m_objectParam->GetHeight());
    }

    m_label->setFixedSize(size());
    show();
}

void TrainView::RunItemsChange()
{
    if (mProtocolData == NULL || mProtocolData->items_change.size() == 0)
        return;

    for (auto it = mProtocolData->items_change.begin(); it != mProtocolData->items_change.end(); it++)
    {
        if (!it.key().compare(m_objectParam->GetName()))
        {
            m_change = true;

            if (it.value().x != DEFAULTVAL)
                m_change_x = it.value().x;
            else
                m_change_x = m_objectParam->GetX();
            if (it.value().y != DEFAULTVAL)
                m_change_y = it.value().y;
            else
                m_change_y = m_objectParam->GetY();
            if (it.value().w != DEFAULTVAL)
                m_change_w = it.value().w;
            else
                m_change_w = m_objectParam->GetWidth();
            if (it.value().h != DEFAULTVAL)
                m_change_h = it.value().h;
            else
                m_change_h = m_objectParam->GetHeight();
            if (it.value().content != "")
            {
                QStringList list = it.value().content.split("$$");
                if (list.size() == 2)
                {
                    if (list.at(0) != "")
                        url = list.at(0);
                    if (list.at(1) != "")
                        m_pos_url = list.at(1);
                }
            }
        }
    }
}

QString TrainView::FindFile(QString prefix, QString name)
{
    if (name == "" || name == "hide")
        return "";

    QString ret;

    ret = myapp::find_file_single(prefix, name);
    if (ret != "")
    {
        AddSuffix(ret);
        return ret;
    }

    return "";
}

void TrainView::ShowUrl()
{
#ifdef __WIN32__
if (mPrefix == "")
    mPrefix = QString("%1/img/").arg(myapp::mDynamicMapParam->m_project_path);
#endif

    RunItemsChange();

    LOG_QDEBUG << m_objectParam->GetObjectName() << "before find: " << url;
    url = FindFile(mPrefix, url);

    if (m_pos_url != "")
    {
        LOG_QDEBUG << m_objectParam->GetObjectName() << "before find: " << m_pos_url;
        m_pos_url = FindFile(mPrefix, m_pos_url);
    }

    if (url != "")
    {
        LOG_QDEBUG << m_objectParam->GetObjectName() << "after find: " << url;
        FinalShow(url);

        if (m_pos_url != "")
        {
            LOG_QDEBUG << m_objectParam->GetObjectName() << "after find: " << m_pos_url;
        }
    }
}

void TrainView::ShowObject()
{
    if (!m_paramIdentity || !m_objectParam) return;

    url = "car_tc1";
    m_pos_url = "car_right_1";

    if (mFilename.contains("mirror"))
    {
        url = "car_tc1_mirror";
        m_pos_url = "car_left_1";
    }

    if (mProtocolData)
    {
        if (mProtocolData->key_position == 2)
        {
            if (mFilename.contains("mirror"))
                url = "car_tc2_mirror";
            else
                url = "car_tc2";
        }

        int car_num = mProtocolData->car_number;
        bool is_mirror = mProtocolData->file_path.contains("mirror");
        int run_dir = RUN_INVALID;
        int start_id = mProtocolData->start_id;
        int stop_id = mProtocolData->stop_id;
        if (start_id <= stop_id)
            run_dir = RUN_UP;
        else
            run_dir = RUN_DOWN;

        if (run_dir == RUN_INVALID)
            return;

        if (mProtocolData->key_position == 1)
        {
            if (is_mirror)
                m_pos_url = QString("car_left_%1").arg(car_num);
            else
                m_pos_url = QString("car_right_%1").arg(car_num);
        }

        if (mProtocolData->key_position == 2)
        {
            if (is_mirror)
                m_pos_url = QString("car_right_%1").arg(car_num);
            else
                m_pos_url = QString("car_left_%1").arg(car_num);
        }
    }

    ShowUrl();
}

void TrainView::StopGifEnd(int frame)
{
    if (m_movie == NULL)
        return;

    int frame_count = m_movie->frameCount();
    if (frame == frame_count - 1)
    {
        m_movie->stop();
        FinalShow(m_pos_url);
    }
}

void TrainView::GetAttribute(std::string& attribute)
{
    std::string jsonStr;
    Json::Value base;
    Json::StreamWriterBuilder writerBuilder;
    std::ostringstream os;

    base["zindex"] = QString::number(m_objectParam->GetIndex()).toStdString();
    base["stid"] = QString::number(m_objectParam->GetStId()).toStdString();
    base["x"] = QString::number(m_objectParam->GetX()).toStdString();
    base["y"] = QString::number(m_objectParam->GetY()).toStdString();
    base["w"] = QString::number(m_objectParam->GetWidth()).toStdString();
    base["h"] = QString::number(m_objectParam->GetHeight()).toStdString();
    base["name"] = m_objectParam->GetName().toStdString();

    std::unique_ptr<Json::StreamWriter> jsonWriter(writerBuilder.newStreamWriter());
    jsonWriter->write(base, &os);
    jsonStr = os.str();

    attribute = jsonStr;
}

void TrainView::SetAttribute(std::string jsonStr)
{
    bool res;
    JSONCPP_STRING errs;
    Json::Value root;
    Json::CharReaderBuilder readerBuilder;
    std::unique_ptr<Json::CharReader> const jsonReader(readerBuilder.newCharReader());
    res = jsonReader->parse(jsonStr.c_str(), jsonStr.c_str()+jsonStr.length(), &root, &errs);

    if (!res || !errs.empty())
         LOG_QDEBUG<<__FUNCTION__<<"json parse faild"<<QString::fromStdString(errs);

    if (CheckJsonValueType(root,"zindex",Json::stringValue))
         m_objectParam->SetIndex(QString::fromStdString(root["zindex"].asString()).toInt());

    if (CheckJsonValueType(root,"stid",Json::stringValue))
         m_objectParam->SetStId(QString::fromStdString(root["stid"].asString()).toInt());

    if (CheckJsonValueType(root,"x",Json::stringValue))
        m_objectParam->SetX(QString::fromStdString(root["x"].asString()).toInt());

    if (CheckJsonValueType(root,"y",Json::stringValue))
        m_objectParam->SetY(QString::fromStdString(root["y"].asString()).toInt());

    if (CheckJsonValueType(root,"w",Json::stringValue))
         m_objectParam->SetWidth(QString::fromStdString(root["w"].asString()).toInt());

    if (CheckJsonValueType(root,"h",Json::stringValue))
         m_objectParam->SetHeight(QString::fromStdString(root["h"].asString()).toInt());

    if (CheckJsonValueType(root,"name",Json::stringValue))
         m_objectParam->SetName(QString::fromStdString(root["name"].asString()));
}

void TrainView::ParseXML(QDomElement* xmlDomEle)
{
    if (NULL == m_paramIdentity)
        m_paramIdentity = new TrainViewParam;

    m_objectParam->SetIndex((xmlDomEle->attribute("zindex","0")).toInt());
    m_objectParam->SetStId((xmlDomEle->attribute("stid","0")).toInt());
    m_objectParam->SetX((xmlDomEle->attribute("x","0")).toInt());
    m_objectParam->SetY((xmlDomEle->attribute("y","0")).toInt());
    m_objectParam->SetWidth((xmlDomEle->attribute("w","0")).toInt());
    m_objectParam->SetHeight((xmlDomEle->attribute("h","0")).toInt());
    m_objectParam->SetName(xmlDomEle->attribute("name",""));
}

void TrainView::PacketXML(QDomElement* dom)
{
    QDomDocument document;
    *dom = document.createElement("item");
    dom->setAttribute("type",m_objectParam->GetObjectName());
    dom->setAttribute("zindex", QString::number(m_objectParam->GetIndex()));
    dom->setAttribute("stid", QString::number(m_objectParam->GetStId()));
    dom->setAttribute("x", QString::number(m_objectParam->GetX()));
    dom->setAttribute("y", QString::number(m_objectParam->GetY()));
    dom->setAttribute("w", QString::number(m_objectParam->GetWidth()));
    dom->setAttribute("h", QString::number(m_objectParam->GetHeight()));
    dom->setAttribute("name", m_objectParam->GetName());
}

